/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package minijava.visitor;

import minijava.SintaxeAbstrata.*;


public class BuildSymbolTable extends TypeDepthFirstVisitor {

    SymbolTable symbolTable;

    public BuildSymbolTable(){
        symbolTable = new SymbolTable();
    }

    public SymbolTable getSymTab(){
        return symbolTable;
    }

    private Class currClass;
    private Method currMethod;

    @Override
  public Type visit(Goal n) {
    n.m.accept(this);
    for ( int i = 0; i < n.cl.size(); i++ ) n.cl.elementAt(i).accept(this);

    return null;
  }

    @Override
  public Type visit(MainClass n) {
    symbolTable.addClass( n.i1.toString(), null);
    currClass = symbolTable.getClass(n.i1.toString());
    currMethod = new Method ("main", new IdentifierType("void"));
    currMethod.addVar(n.i2.toString(),
                      new IdentifierType("String[]"));
    n.s.accept(this);

    currMethod = null;

    return null;
  }

  public Type visit(ClassDeclSimple n) {
    if(!symbolTable.addClass( n.i.toString(), null)){
        System.out.println("Classe " +  n.i.toString() + "ja existe" );
        System.exit(-1);
    }
    currClass =  symbolTable.getClass(n.i.toString());
    for ( int i = 0; i < n.vl.size(); i++ ) n.vl.elementAt(i).accept(this);
    for ( int i = 0; i < n.ml.size(); i++ ) n.ml.elementAt(i).accept(this);
    
    return null;
  }

    @Override
  public Type visit(ClassDeclExtends n) {
    if(!symbolTable.addClass( n.i.toString(),  n.j.toString())){
        System.out.println("Classe " +  n.i.toString()
                           + " ja esta definida" );
        System.exit(-1);
    }
    currClass = symbolTable.getClass(n.i.toString());

    for ( int i = 0; i < n.vl.size(); i++ ) n.vl.elementAt(i).accept(this);
    for ( int i = 0; i < n.ml.size(); i++ ) n.ml.elementAt(i).accept(this);
    
    return null;
  }

    @Override
  public Type visit(VarDecl n) {
     Type t =  n.t.accept(this);
     String id =  n.i.toString();

      if (currMethod == null){
          if (!currClass.addVar(id,t)){
              System.out.println("Identificador " + id + " ja existe");
              System.exit(-1);
          }
      } else {
          if (!currMethod.addVar(id,t)){
              System.out.println("Identificador " + id + " ja existe");
              System.exit(-1);
          }
      }
    return null;
  }

    @Override
  public Type visit(MethodDecl n) {
    Type t = n.t.accept(this);
    String id = n.i.toString();

    if (!currClass.addMethod(id,t)){
        System.out.println("Metodo " + id  + " ja existe");
        System.exit(-1);
    }

    currMethod = currClass.getMethod(id);
    for ( int i = 0; i < n.fl.size(); i++ )  n.fl.elementAt(i).accept(this);
    for ( int i = 0; i < n.vl.size(); i++ )  n.vl.elementAt(i).accept(this);
    for ( int i = 0; i < n.sl.size(); i++ )  n.sl.elementAt(i).accept(this);
    n.e.accept(this);
    currMethod = null;
    return null;
  }

    @Override
  public Type visit(Formal n) {

    Type t = n.t.accept(this);
    String id = n.i.toString();

    if (!currMethod.addParam(id,t)){
        System.out.println("Formal" + id + " ja existe");
        System.exit(-1);
    }
    return null;
  }

    @Override
  public Type visit(IntArrayType n) {
    return n;
  }

    @Override
  public Type visit(BooleanType n) {
    return n;
  }

    @Override
  public Type visit(IntegerType n) {
    return n;
  }

    @Override
  public Type visit(IdentifierType n) {
    return n;
  }

    @Override
  public Type visit(Block n) {
    for ( int i = 0; i < n.sl.size(); i++ ) {
        n.sl.elementAt(i).accept(this);
    }
    return null;
  }
}